﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.Caching;

namespace IRC.IRepairClouds.DataLayer.Cache
{
    [DebuggerDisplay(@"\{ UserCached [{Id}, {Login}] }")]
    public class UserCached
    {
        public Guid Id { get; private set; }
        public string Login { get; private set; }
        public string Name { get; private set; }
        public EUserRole.Role Role { get; private set; }
        public Guid PartnerGuid{ get; private set; }
        public TimeZoneCachedLoaderById TimeZone { get; private set; }
        public EUser CachedEntity(ICloudRepairEntities dbContext)
        {
            return dbContext.CachedEUser(Id);
        }

        public static IEnumerable<UserCached> CreateInitialLoad()
        {
            using (ICloudRepairEntities db = new ICloudRepairEntities()) {
                foreach (var user in db.Users.Select(i => new {
                    i.ID,
                    i.Login,
                    i.Name,
                    i.Partner.PartnerId,
                    RoleId = i.RoleId
                })) {
                    var ud = new UserCached();
                    ud.Id = user.ID;
                    ud.Login = user.Login;
                    ud.Name = user.Name;
                    ud.Role = (EUserRole.Role)user.RoleId;
                    ud.PartnerGuid = user.PartnerId;
                    yield return ud;
                }
            }
        }

        public override string ToString()
        {
            return string.Format("Id=[{0}] | Login=[{1}] | Role=[{2}], TimeZone=[{3}]", Id, Login, Role, TimeZone.Id);
        }

        public override bool Equals(object obj)
        {
            return (obj is UserCached) && ((obj as UserCached).Id == Id);
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public static bool operator ==(UserCached a, UserCached b)
        {
            if (System.Object.ReferenceEquals(a, b))
                return true;
            if (((object)a == null) || ((object)b == null))
                return false;
            return a.Equals(b);
        }

        public static bool operator !=(UserCached a, UserCached b)
        {
            return !(a == b);
        }
    }

    public class UserCachedLoaderById : DataCachedLoader<UserCached>
    {
        public int Id { get; private set; }

        public UserCachedLoaderById(int id)
        {
            Id = id;
        }

        protected override UserCached Load()
        {
            return CacheManager.Users[Id];
        }

        public override bool Equals(object obj)
        {
            return (obj is UserCachedLoaderById) && ((obj as UserCachedLoaderById).Id == Id);
        }

        public override int GetHashCode()
        {
            return Id.GetHashCode();
        }

        public static bool operator ==(UserCachedLoaderById a, UserCachedLoaderById b)
        {
            if (System.Object.ReferenceEquals(a, b))
                return true;
            if (((object)a == null) || ((object)b == null))
                return false;
            return a.Equals(b);
        }

        public static bool operator !=(UserCachedLoaderById a, UserCachedLoaderById b)
        {
            return !(a == b);
        }
    }

    public class UserStaticCacheManager : StaticCacheManager<UserCached>
    {
        protected override IEnumerable<object[]> GetCachedKeys(UserCached obj)
        {
            yield return new object[] { obj.Id };
            yield return new object[] { obj.Login.ToLowerInvariantN() };
        }

        protected override void InitialLoad()
        {
            base.InsertInitialLoadBase(UserCached.CreateInitialLoad());
        }

        public UserCached this[int id]
        {
            get { return GetBase(id); }
        }

        public UserCached this[string login]
        {
            get { return GetBase(login.ToLowerInvariantN()); }
        }

        public UserCached Current
        {
            get
            {
                var login = EUser.Get();
                if (login != null)
                    return this[login];
                return null;
            }
        }
    }
}
